﻿using System;
using System.Linq;
using ECode.ECommon.Extensions;
using ECode.ModbusTester.Lib.Helpers;

namespace ECode.ModbusTester.Lib.ViewModel
{
    /// <summary>
    /// Modbus指令生成器ViewModel
    /// </summary>
    public class ModbusCmdViewModel : BaseViewModel
    {
        /// <summary>
        /// 仪表地址
        /// </summary>
        public decimal InstrAddr { get; set; }
        /// <summary>
        /// 起始地址
        /// </summary>
        public decimal Addr { get; set; }
        /// <summary>
        /// 操作类型
        /// </summary>
        public string OptType { get; set; }
        /// <summary>
        /// 功能码
        /// </summary>
        public string FunCode { get; set; }
        /// <summary>
        /// 获取长度
        /// </summary>
        public decimal GetLen { get; set; }
        /// <summary>
        /// 写入值
        /// </summary>
        public string WriteValue { get; set; }
        /// <summary>
        /// 数据类型
        /// </summary>
        public string DataType { get; set; }
        /// <summary>
        /// 指令
        /// </summary>
        private string _cmd;
        public string Cmd { get { return _cmd; } set { _cmd = value; OnPropertyChanged("Cmd"); } }
        /// <summary>
        /// 根据操作不同，获取不同功能码
        /// </summary>
        /// <returns></returns>
        public string[] GetFunCode()
        {
            if (string.IsNullOrWhiteSpace(OptType)) return new string[0];
            if (OptType.Equals("读操作"))
                return Enum.GetNames(typeof(FunCodeRead));
            if (OptType.Equals("写操作"))
                return Enum.GetNames(typeof(FunCodeWrite));
            return new string[0];
        }
        /// <summary>
        /// 生成指令
        /// </summary>
        /// <returns></returns>
        public void Create()
        {
            var cmd = string.Empty;
            if (OptType.Equals("读操作"))
                cmd = CreateRead();
            if (OptType.Equals("写操作"))
                cmd = CreateWrite();
            var tmp = cmd.ToBytes("HEX");
            var cdd = CrcHelper.CalculateCRC(tmp, tmp.Length);
            Cmd = string.Join(" ", tmp.Concat(cdd).Select(t => t.ToString("X2")));
        }

        private string GetFunCodeValue()
        {
            if (OptType.Equals("读操作"))
                return ((int)((FunCodeRead)Enum.Parse(typeof(FunCodeRead), FunCode))).ToString().PadLeft(2, '0');
            if (OptType.Equals("写操作"))
                return ((int)((FunCodeRead)Enum.Parse(typeof(FunCodeWrite), FunCode))).ToString().PadLeft(2, '0');
            return null;
        }
        private string CreateRead()
        {
            return ((int)InstrAddr).ToString().ToHex(2) +
                   GetFunCodeValue() +
                   ((int)Addr - 1).ToString("X4") +
                   ((int)GetLen).ToString("X4");
        }

        private string CreateWrite()
        {
            return ((int)InstrAddr).ToString().PadLeft(2, '0') +
                   GetFunCodeValue() +
                   ((int)Addr - 1).ToString("X4") +
                   WriteValue.ToConvert(DataType);
        }
    }

    enum FunCodeRead
    {
        读线圈状态 = 01,
        读输入状态 = 02,
        读保持寄存器 = 03,
        读输入寄存器 = 04
    }

    enum FunCodeWrite
    {
        强置单线圈 = 05,
        预置单寄存器 = 06,
        强置多线圈 = 15,
        强置多寄存器 = 16
    }
}
